
#ifndef _MEMORY_H
#define _MEMORY_H

#include "riscv.h"
#include "types.h"
#include "list.h"

struct Page {
    uint64 ref;                        // page frame's reference counter
    uint64 flags;                 // array of flags that describe the status of the page frame
    uint64 property;          // the num of free block, used in first fit pm manager
    list_entry_t page_link;         // free list link
};

struct physical_memory_manager {
    const char *pmm_manager_name;  
    void (*init_physical_memory)(void);  
    void (*init_memmap)(uintptr_t base,size_t n);  
    uintptr_t (*alloc_pages)( size_t n); 
    void (*free_pages)( uintptr_t base, size_t n);  
    size_t (*nr_free_pages)(void);  // return the number of free pages
    void (*pmm_check)(void);
};
extern const struct physical_memory_manager pmm_manager;

#define alloc_page() pmm_manager.alloc_pages(1)
#define free_page(page) pmm_manager.free_pages(page,1)

/* free_area_t - maintains a doubly linked list to record free (unused) pages */
typedef struct {
    list_entry_t free_list;         // the list header
    unsigned int nr_free;           // # of free pages in this free list
} free_area_t;

// convert list entry to page
#define le2page(le, member)                 \
    to_struct((le), struct Page, member)

uintptr_t vm_init();
uintptr_t page_alloc();

pagetable_t uvmcreate();
void printMem();


bool pa_in_freelist(uint64 pa);

#endif